using GrapeCity.Forguncy.Commands;
using GrapeCity.Forguncy.Plugin;
using GrapeCity.Forguncy.Log;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using TextEmbedding.Core;

namespace TextEmbedding
{
    [Icon("pack://application:,,,/TextEmbedding;component/Resources/Icon.png")]
    [Category("分词与向量化")]
    public class BM25 : Command, ICommandExecutableInServerSideAsync
    {
        [FormulaProperty]
        [DisplayName("被向量化的文本")]
        [Description("需要进行BM25向量化的文本。")]
        [OrderWeight(1)]
        public object TextExpr { get; set; }

        [FormulaProperty]
        [DisplayName("用作词表的文本数组")]
        [Description("用来提炼词表的文本数组。")]
        [OrderWeight(10)]
        public object TextArrExpr { get; set; }

        [FormulaProperty]
        [DisplayName("K1（词频饱和控制）")]
        [Description("高频出现的词对得分的影响程度，通常在0.5到2.0之间，如新闻检索类倾向于0.75，产品介绍搜索倾向于1.75。")]
        [OrderWeight(30)]
        public object K1Expr { get; set; } = 1.5;


        [FormulaProperty]
        [DisplayName("B（文档长度归一化）")]
        [Description("文本长度对得分的影响程度。通常在0.25到0.75之间，如新闻标题检索倾向于0.25，论文或报告检索倾向于0.75")]
        [OrderWeight(40)]
        public object BExpr { get; set; } = 0.75;

        [FormulaProperty]
        [DisplayName("维度")]
        [Description("BM25向量化的维度，返回时将基于这个属性进行截断或填充。在词表的基础上，文档中不存在的词填0，多余的词截断")]
        [OrderWeight(20)]
        public object DimExpr { get; set; }

        [ResultToProperty]
        [DisplayName("向量化结果")]
        [OrderWeight(99)]
        public string ResultTo { get; set; } = "Vector";

        public async Task<ExecuteResult> ExecuteAsync(IServerCommandExecuteContext dataContext)
        {
            var text = (await dataContext.EvaluateFormulaAsync(TextExpr))?.ToString() ?? "";
            var all = await dataContext.EvaluateFormulaAsync(TextArrExpr);
            var dim = (await dataContext.EvaluateFormulaAsync(DimExpr))?.ToString() ?? "0";
            var k1Str = (await dataContext.EvaluateFormulaAsync(K1Expr))?.ToString() ?? "1.5";
            var bStr = (await dataContext.EvaluateFormulaAsync(BExpr))?.ToString() ?? "0.75";

            if (!int.TryParse(dim, out int dimNumber) || dimNumber <= 0)
            {
                throw new Exception("维度必须是大于0的整数");
            }

            if (string.IsNullOrWhiteSpace(text))
            {
                dataContext.Parameters[ResultTo] = new float[dimNumber]; // 空文本返回全0向量
            }
            else
            {
                ITextEmbedding embedding = new Core.BM25Embedding(TextCollectionConverter.ToStringList(all), double.Parse(k1Str), double.Parse(bStr));
                var vector = embedding.Embedding(dimNumber, text);
                dataContext.Parameters[ResultTo] = vector;  // 把计算的结果设置到结果变量中
            }



            return new ExecuteResult();
        }

        public override string ToString()
        {
            return "BM25向量化";
        }

        public override CommandScope GetCommandScope()
        {
            return CommandScope.ExecutableInServer;
        }
    }
}
